/*
 * Copyright 2020-2021 redragon.dongbin
 *
 * This file is part of redragon-erp/赤龙ERP.

 * redragon-erp/赤龙ERP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * redragon-erp/赤龙ERP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with redragon-erp/赤龙ERP.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.erp.prod.wip.service.spring;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.redragon.commons.lang.Times;
import org.redragon.framework.hibernate.data.SnowFlake;
import org.redragon.framework.hibernate.model.Pages;
import org.redragon.framework.util.ShiroUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.erp.common.inv.input.dao.model.InvInputHead;
import com.erp.common.inv.input.dao.model.InvInputLine;
import com.erp.common.inv.input.service.InvInputHeadService;
import com.erp.common.inv.input.service.InvInputLineService;
import com.erp.common.inv.output.dao.model.InvOutputHead;
import com.erp.common.inv.output.dao.model.InvOutputLine;
import com.erp.common.inv.output.service.InvOutputHeadService;
import com.erp.common.inv.output.service.InvOutputLineService;
import com.erp.hr.dao.model.HrStaffInfoRO;
import com.erp.hr.service.HrCommonService;
import com.erp.prod.craft.dao.model.ProdWorkCraft;
import com.erp.prod.craft.dao.model.ProdWorkCraftProcedure;
import com.erp.prod.craft.dao.model.ProdWorkCraftProcedureCO;
import com.erp.prod.craft.service.ProdWorkCraftProcedureService;
import com.erp.prod.craft.service.ProdWorkCraftService;
import com.erp.prod.wip.dao.ProdWipTaskProcedureDao;
import com.erp.prod.wip.dao.model.ProdWipTask;
import com.erp.prod.wip.dao.model.ProdWipTaskProcedure;
import com.erp.prod.wip.dao.model.ProdWipTaskProcedureCO;
import com.erp.prod.wip.service.ProdWipTaskProcedureService;
import com.erp.prod.wip.service.ProdWipTaskService;

@Service
@Transactional(rollbackFor=Exception.class)
public class ProdWipTaskProcedureServiceImpl implements ProdWipTaskProcedureService {

    //注入Dao
    @Autowired
    private ProdWipTaskProcedureDao prodWipTaskProcedureDao;
    @Autowired
    private ProdWipTaskService prodWipTaskService;
    @Autowired
    private ProdWorkCraftService prodWorkCraftService;
    @Autowired
    private ProdWorkCraftProcedureService prodWorkCraftProcedureService;
    @Autowired
    private HrCommonService hrCommonService;
    @Autowired
    @Qualifier("invInputHeadServiceCommon")
    private InvInputHeadService invInputHeadService;
    @Autowired
    @Qualifier("invInputLineServiceCommon")
    private InvInputLineService invInputLineService;
    @Autowired
    @Qualifier("invOutputHeadServiceCommon")
    private InvOutputHeadService invOutputHeadService;
    @Autowired
    @Qualifier("invOutputLineServiceCommon")
    private InvOutputLineService invOutputLineService;
    
    @Override
    public void insertDataObject(ProdWipTaskProcedure obj) {
        this.prodWipTaskProcedureDao.insertDataObject(obj);
    }

    @Override
    public void updateDataObject(ProdWipTaskProcedure obj) {
        this.prodWipTaskProcedureDao.updateDataObject(obj);
    }
    
    @Override
    public void insertOrUpdateDataObject(ProdWipTaskProcedure obj) {
        this.prodWipTaskProcedureDao.insertOrUpdateDataObject(obj);
    }
    
    @Override
    public String insertOrUpdateWipTaskProcedure(ProdWipTaskProcedure obj){
        //转移时更新下一工序状态
        if(obj.getProcedureShiftType().equals("SHIFT")&&obj.getStatus().equals("SHIFT")&&StringUtils.isNotBlank(obj.getShiftProcedureCode())) {
            this.prodWipTaskProcedureDao.updateWipTaskProcedureForStatus(obj.getTaskCode(), obj.getShiftProcedureCode(), "WORK");
            //插入或更新数据
            this.prodWipTaskProcedureDao.insertOrUpdateDataObject(obj);
        }
        
        //完工时
        if(obj.getProcedureShiftType().equals("FINISH")&&StringUtils.isBlank(obj.getShiftProcedureCode())) {
            //获取当前时间
            Times time = new Times();
            time.getTime();
            
            //修改任务头状态
            this.prodWipTaskService.updateTaskStatus(obj.getTaskCode(), "FINISH");
            //插入入库头
            InvInputHead invInputHead = new InvInputHead();
            invInputHead.setInputHeadCode("WIP-IN-"+time.minute+time.second+"_"+obj.getTaskCode());
            invInputHead.setInputType("WIP_IN");
            invInputHead.setInputSourceType("PROD");
            invInputHead.setInputSourceHeadCode(obj.getTaskCode());
            //获取当前用户职员信息
            HrStaffInfoRO staffInfo = this.hrCommonService.getStaffInfo(ShiroUtil.getPrincipal());
            invInputHead.setStaffCode(staffInfo.getStaffCode());
            invInputHead.setDepartmentCode(staffInfo.getDepartmentCode());
            invInputHead.setInputDate(time.getJavaDate());
            invInputHead.setCreatedBy(ShiroUtil.getPrincipal());
            invInputHead.setCreatedDate(time.getJavaDateTime());
            invInputHead.setOrgCode(ShiroUtil.getOrgCode());
            
            this.invInputHeadService.insertDataObject(invInputHead);
            
            //获取生产任务
            ProdWipTask prodWipTask = this.prodWipTaskService.getDataObject(obj.getTaskCode());
            
            //插入入库行
            InvInputLine invInputLine = new InvInputLine();
            invInputLine.setInputHeadCode(invInputHead.getInputHeadCode());
            invInputLine.setInputLineCode(SnowFlake.getConcurrentId().toString());
            invInputLine.setInputSourceLineCode(obj.getTaskProcedureCode());
            invInputLine.setMaterialCode(prodWipTask.getMaterialCode());
            invInputLine.setInputQuantity(obj.getFinishQuantity());
            invInputLine.setAmount(0D);
            invInputLine.setPrice(0D);
            invInputLine.setUnit(prodWipTask.getMaterialUnit());
            invInputLine.setCreatedBy(ShiroUtil.getPrincipal());
            invInputLine.setCreatedDate(time.getJavaDateTime());
            invInputLine.setOrgCode(ShiroUtil.getOrgCode());
            
            this.invInputLineService.insertDataObject(invInputLine);
            
            //插入或更新数据
            this.prodWipTaskProcedureDao.insertOrUpdateDataObject(obj);
        }
        
        //退货时
        if(obj.getProcedureShiftType().equals("RETURN")&&StringUtils.isBlank(obj.getShiftProcedureCode())) {
            //判断是否存在入库头
            InvInputHead invInputHead = this.invInputHeadService.getInvInputHeadBySourceHeadCode(obj.getTaskCode());
            if(invInputHead!=null) {
                //判读是否存在入库行
                List<InvInputLine> invInputLineList = this.invInputLineService.getInvInputLineListByHeadCode(invInputHead.getInputHeadCode());
                if(invInputLineList!=null&&invInputLineList.size()>0) {
                    if(obj.getFinishQuantity()<=invInputLineList.get(0).getInputQuantity()) {
                        //获取当前时间
                        Times time = new Times();
                        time.getTime();
                        
                        //修改任务头状态
                        this.prodWipTaskService.updateTaskStatus(obj.getTaskCode(), "ASSIGN");
                        //插入出库头
                        InvOutputHead invOutputHead = new InvOutputHead();
                        invOutputHead.setOutputHeadCode("WIP-OUT-"+time.minute+time.second+"_"+obj.getTaskCode());
                        invOutputHead.setOutputType("WIP_OUT");
                        invOutputHead.setOutputSourceType("PROD");
                        invOutputHead.setOutputSourceHeadCode(obj.getTaskCode());
                        invOutputHead.setWarehouseCode(invInputHead.getWarehouseCode());
                        //获取当前用户职员信息
                        HrStaffInfoRO staffInfo = this.hrCommonService.getStaffInfo(ShiroUtil.getPrincipal());
                        invOutputHead.setStaffCode(staffInfo.getStaffCode());
                        invOutputHead.setDepartmentCode(staffInfo.getDepartmentCode());
                        invOutputHead.setOutputDate(time.getJavaDate());
                        invOutputHead.setCreatedBy(ShiroUtil.getPrincipal());
                        invOutputHead.setCreatedDate(time.getJavaDateTime());
                        invOutputHead.setOrgCode(ShiroUtil.getOrgCode());
                        
                        this.invOutputHeadService.insertDataObject(invOutputHead);
                        
                        //获取生产任务
                        ProdWipTask prodWipTask = this.prodWipTaskService.getDataObject(obj.getTaskCode());
                        
                        //插入出库行
                        InvOutputLine invOutputLine = new InvOutputLine();
                        invOutputLine.setOutputHeadCode(invOutputHead.getOutputHeadCode());
                        invOutputLine.setOutputLineCode(SnowFlake.getConcurrentId().toString());
                        invOutputLine.setOutputSourceLineCode(obj.getTaskProcedureCode());
                        invOutputLine.setMaterialCode(prodWipTask.getMaterialCode());
                        invOutputLine.setOutputQuantity(obj.getFinishQuantity());
                        invOutputLine.setPrice(0D);
                        invOutputLine.setAmount(0D);
                        invOutputLine.setUnit(prodWipTask.getMaterialUnit());
                        invOutputLine.setCreatedBy(ShiroUtil.getPrincipal());
                        invOutputLine.setCreatedDate(time.getJavaDateTime());
                        invOutputLine.setOrgCode(ShiroUtil.getOrgCode());
                        
                        this.invOutputLineService.insertDataObject(invOutputLine);
                        
                        //插入或更新数据
                        this.prodWipTaskProcedureDao.insertOrUpdateDataObject(obj);
                    }else {
                        return "退回工厂的数量不能大于工厂入库的数量";
                    }
                }else {
                    return "工厂入库单行存在问题";
                }
            }else {
                return "工厂入库单不存在或入库单未审批";
            }
        }
        
        return "成功";
    }

    @Override
    public void deleteDataObject(ProdWipTaskProcedure obj) {
        this.prodWipTaskProcedureDao.deleteDataObject(obj);
    }

    @Override
    public List<ProdWipTaskProcedure> getDataObjects() {
        return this.prodWipTaskProcedureDao.getDataObjects();
    }

    @Override
    public ProdWipTaskProcedure getDataObject(int id) {
        return this.prodWipTaskProcedureDao.getDataObject(id);
    }

    @Override
    public ProdWipTaskProcedure getDataObject(String code) {
        return this.prodWipTaskProcedureDao.getDataObject(code);
    }

    @Override
    public List<ProdWipTaskProcedure> getDataObjects(ProdWipTaskProcedureCO paramObj) {
        return this.prodWipTaskProcedureDao.getDataObjects(paramObj);
    }

    @Override
    public List<ProdWipTaskProcedure> getDataObjects(Pages pages) {
        return this.prodWipTaskProcedureDao.getDataObjects(pages);
    }
    
    @Override
    public List<ProdWipTaskProcedure> getDataObjects(Pages pages, ProdWipTaskProcedureCO paramObj) {
        return this.prodWipTaskProcedureDao.getDataObjects(pages, paramObj);
    }
    
    @Override
    public List<Map<String, Object>> getDataObjectsArray(Pages pages, ProdWipTaskProcedureCO paramObj) {
        return this.prodWipTaskProcedureDao.getDataObjectsArray(pages, paramObj);
    }
    
    @Override
    public List<ProdWipTaskProcedure> getDataObjectsForDataAuth(String dataAuthSQL, Pages pages, ProdWipTaskProcedureCO paramObj) {
        return this.prodWipTaskProcedureDao.getDataObjectsForDataAuth(dataAuthSQL, pages, paramObj);
    }
    
    @Override
    public List<ProdWipTaskProcedure> getWipTaskProcedureListByTaskCode(Pages pages, ProdWipTaskProcedureCO paramObj) {
        return this.prodWipTaskProcedureDao.getWipTaskProcedureListByTaskCode(pages, paramObj);
    }
    
    @Override
    public void updateLineForVersion(String code) {
        this.prodWipTaskProcedureDao.updateLineForVersion(code);
    }
    
    @Override
    public String createWipTaskProcedure(String taskCode) {
        Pages pages = new Pages();
        pages.setPage(1);
        pages.setMax(100);
        
        try {
            //获取车间任务生产工序
            ProdWipTaskProcedureCO prodWipTaskProcedureCO = new ProdWipTaskProcedureCO();
            prodWipTaskProcedureCO.setTaskCode(taskCode);
            List<ProdWipTaskProcedure> prodWipTaskProcedureList = this.prodWipTaskProcedureDao.getWipTaskProcedureListByTaskCode(pages, prodWipTaskProcedureCO);
            int num = 0;
            String createFlag = "Y";
            //循环生产工序
            for(ProdWipTaskProcedure prodWipTaskProcedure: prodWipTaskProcedureList) {
                num = 1;
                //bbc 工序未发生工序移动则可以删除
//                if(prodWipTaskMaterial.getGetQuantity()!=null&&prodWipTaskMaterial.getGetQuantity()>0) {
//                    createFlag = "N";
//                    break;
//                }
            }
            
            //如果当前物料列表已领料，则不能重新生成物料需求
            if(createFlag.equals("N")) {
                return "{\"result\": \"hint\",\"message\": \"生产工序已发生移动，无法重新生成\"}";
            }
            
            //如果存在生产工序，则先删除后创建
            if(num==1) {
                this.prodWipTaskProcedureDao.deleteWipTaskProcedureListByTaskCode(taskCode);
            }
            
            //获取车间任务信息
            ProdWipTask prodWipTask = this.prodWipTaskService.getDataObject(taskCode);
            Date taskStartDate = prodWipTask.getStartDate();
            //获取工艺路线
            ProdWorkCraft prodWorkCraft = this.prodWorkCraftService.getProdWorkCraftByMaterialCode(prodWipTask.getMaterialCode());
            //获取工艺列表
            ProdWorkCraftProcedureCO prodWorkCraftProcedureCO = new ProdWorkCraftProcedureCO();
            prodWorkCraftProcedureCO.setCraftCode(prodWorkCraft.getCraftCode());
            
            List<ProdWorkCraftProcedure> prodWorkCraftProcedureList = this.prodWorkCraftProcedureService.getProcedureListByCraftCode(pages, prodWorkCraftProcedureCO);
            
            Date procedureStartDate = taskStartDate;
            //循环获取车间任务生产工序
            int a = 0;
            for(int i=0; i<prodWorkCraftProcedureList.size(); i++) {
                ProdWipTaskProcedure prodWipTaskProcedure = new ProdWipTaskProcedure();
                prodWipTaskProcedure.setStartDate(procedureStartDate);
                //计算结束时间
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Times time = new Times();
                time.changeDate(df.format(procedureStartDate), Calendar.DAY_OF_MONTH, (int)Math.ceil(prodWorkCraftProcedureList.get(i).getProducePreDays()));
                procedureStartDate = time.getJavaDateTime();
                prodWipTaskProcedure.setEndDate(time.getJavaDateTime());
                
                prodWipTaskProcedure.setCostAmount(0D);
                prodWipTaskProcedure.setProcedureCode(prodWorkCraftProcedureList.get(i).getProcedureCode());
                if(i+1<prodWorkCraftProcedureList.size()) {
                    prodWipTaskProcedure.setShiftProcedureCode(prodWorkCraftProcedureList.get(i+1).getProcedureCode());
                }
                prodWipTaskProcedure.setWorkCenterCode(prodWorkCraftProcedureList.get(i).getWorkCenterCode());
                prodWipTaskProcedure.setProducePreDays(prodWorkCraftProcedureList.get(i).getProducePreDays());
                prodWipTaskProcedure.setTaskCode(taskCode);
                prodWipTaskProcedure.setTaskProcedureCode(SnowFlake.getConcurrentId().toString());
                prodWipTaskProcedure.setStatus("WAIT");
                if(a==0) {
                    prodWipTaskProcedure.setStatus("WORK");
                    a++;
                }
                
                this.prodWipTaskProcedureDao.insertDataObject(prodWipTaskProcedure);
            }
            
            return "{\"result\":\"success\"}";
        }catch(Exception e) {
            return "{\"result\":\"error\"}";
        }
    }
    
}